package com.project.server.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.project.server.common.exception.BusinessException;
import com.project.server.entity.Consultation;
import com.project.server.entity.ConsultationMessage;
import com.project.server.entity.PatientInfo;
import com.project.server.entity.SysUser;
import com.project.server.mapper.ConsultationMapper;
import com.project.server.mapper.ConsultationMessageMapper;
import com.project.server.mapper.PatientInfoMapper;
import com.project.server.mapper.SysUserMapper;
import com.project.server.service.ConsultationService;
import com.project.server.vo.ConsultationDetailVO;
import com.project.server.vo.ConsultationVO;
import com.project.server.vo.doctor.DoctorVO;
import com.project.server.vo.ConsultationStats;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import lombok.extern.slf4j.Slf4j;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.time.LocalDate;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.project.server.dto.ConsultationStatsDTO;
import com.project.server.service.DoctorService;

@Service
@Slf4j
public class ConsultationServiceImpl extends ServiceImpl<ConsultationMapper, Consultation> implements ConsultationService {

    @Autowired
    private ConsultationMapper consultationMapper;

    @Autowired
    private ConsultationMessageMapper consultationMessageMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private PatientInfoMapper patientInfoMapper;

    @Override
    @Transactional
    public Long createConsultation(Long doctorId,Long userId) {
        Consultation consultation = new Consultation();
        consultation.setDoctorId(doctorId);
        consultation.setUserId(userId);
        consultation.setStatus(0);
        consultation.setCreateTime(LocalDateTime.now());
        consultation.setUpdateTime(LocalDateTime.now());

        consultationMapper.insert(consultation);
        // 医生 问诊+1
        SysUser sysUser = sysUserMapper.selectById(doctorId);
        int consultationCount = sysUser.getConsultationCount();
        sysUser.setConsultationCount(consultationCount + 1);
        sysUserMapper.updateById(sysUser);

        return consultation.getId();
    }

    @Override
    public ConsultationDetailVO getConsultationDetail(Long id) {
        Consultation consultation = consultationMapper.selectById(id);
        if (consultation == null) {
            throw new RuntimeException("问诊记录不存在");
        }

        SysUser doctor = sysUserMapper.selectById(consultation.getDoctorId());

        ConsultationDetailVO vo = new ConsultationDetailVO();
        vo.setId(consultation.getId());
        vo.setStatus(consultation.getStatus());
        vo.setCreateTime(consultation.getCreateTime());

        DoctorVO doctorVO = new DoctorVO();
        BeanUtils.copyProperties(doctor, doctorVO);
        vo.setDoctor(doctorVO);

        Long userId = consultation.getUserId();
        SysUser sysUser = sysUserMapper.selectById(userId);
        vo.setAge(sysUser.getAge());
        vo.setGender(sysUser.getGender());
        vo.setRealName(sysUser.getRealName());
        vo.setDoctorAvatar(doctor.getAvatar());
        vo.setUserAvatar(sysUser.getAvatar());

        // 获取对话
        Long consultationId = consultation.getId();
        List<ConsultationMessage> messages = consultationMessageMapper.selectList(
                new LambdaQueryWrapper<ConsultationMessage>().eq(ConsultationMessage::getConsultationId, consultationId)
                        );
        vo.setMessages(messages);

        return vo;
    }

    @Override
    public Page<Consultation> getConsultations(Long doctorId, Integer current, Integer size, Integer status) {
        Page<Consultation> page = new Page<>(current, size);

        LambdaQueryWrapper<Consultation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Consultation::getDoctorId, doctorId)
                .eq(status != null, Consultation::getStatus, status)
                .orderByDesc(Consultation::getCreateTime);

        return consultationMapper.selectPage(page, wrapper);
    }

    @Override
    @Transactional
    public void acceptConsultation(Long consultationId) {
        Consultation consultation = getById(consultationId);

        // 更新问诊状态为已接诊
        consultation.setStatus(1);
        updateById(consultation);


        Long doctorId = consultation.getDoctorId();
        Long userId = consultation.getUserId();
        // 添加患者
        Long countNum = patientInfoMapper.selectCount(new LambdaQueryWrapper<PatientInfo>()
                .eq(PatientInfo::getDoctorId, doctorId)
                .eq(PatientInfo::getUserId, userId));
        // 检查是否已经是该医生的患者

        // 如果不存在关系，则添加
        if (countNum == 0) {
            PatientInfo doctorPatient = new PatientInfo();
            doctorPatient.setDoctorId(doctorId);
            doctorPatient.setUserId(userId);
            doctorPatient.setCreateTime(LocalDateTime.now());
            patientInfoMapper.insert(doctorPatient);
        }
    }


    @Override
    @Transactional
    public void rejectConsultation(Long id) {
        Consultation consultation = consultationMapper.selectById(id);
        if (consultation == null) {
            throw new BusinessException("问诊不存在");
        }

        if (consultation.getStatus() != 0) {
            throw new BusinessException("问诊状态不正确");
        }

        consultation.setStatus(3);
        consultationMapper.updateById(consultation);
    }

    @Override
    public void endConsultation(Long id, String remark) {
        Consultation consultation = consultationMapper.selectById(id);
        if (consultation == null) {
            throw new BusinessException("问诊不存在");
        }

        consultation.setStatus(2);
        consultation.setDiagnosis(remark);
        consultationMapper.updateById(consultation);
    }

    @Override
    public ConsultationStats getConsultationStats(Long doctorId) {
        ConsultationStats stats = new ConsultationStats();

        // 获取各状态问诊数量
        LambdaQueryWrapper<Consultation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Consultation::getDoctorId, doctorId);

        // 待接诊数量
        stats.setWaitingCount(count(wrapper.eq(Consultation::getStatus, 0)));

        // 问诊中数量
        stats.setOngoingCount(count(wrapper.eq(Consultation::getStatus, 1)));

        // 已完成数量
        stats.setFinishedCount(count(wrapper.eq(Consultation::getStatus, 2)));

        // 总问诊数量
        stats.setTotalCount(count(wrapper));

        // 今日问诊数量
        LocalDateTime today = LocalDate.now().atStartOfDay();
        stats.setTodayCount(count(wrapper
            .ge(Consultation::getCreateTime, today)
            .lt(Consultation::getCreateTime, today.plusDays(1))));

        // 本周问诊数量
        LocalDateTime weekStart = today.minusDays(today.getDayOfWeek().getValue() - 1);
        stats.setWeekCount(count(wrapper
            .ge(Consultation::getCreateTime, weekStart)
            .lt(Consultation::getCreateTime, weekStart.plusWeeks(1))));

        // 本月问诊数量
        LocalDateTime monthStart = today.withDayOfMonth(1);
        stats.setMonthCount(count(wrapper
            .ge(Consultation::getCreateTime, monthStart)
            .lt(Consultation::getCreateTime, monthStart.plusMonths(1))));

        // 获取评分统计
        Map<String, Object> ratingStats = consultationMapper.selectRatingStats(doctorId);
        if (ratingStats != null) {
            stats.setAvgRating((Double) ratingStats.get("avgRating"));
            stats.setPatientCount((Integer) ratingStats.get("patientCount"));
            stats.setRepeatCount((Integer) ratingStats.get("repeatCount"));
        }

        return stats;
    }


    // 统计数量的工具方法
    private long count(LambdaQueryWrapper<Consultation> wrapper) {
        return consultationMapper.selectCount(wrapper);
    }

    @Override
    public ConsultationStatsDTO getDoctorStats(Long doctorId) {
        ConsultationStatsDTO stats = new ConsultationStatsDTO();

        // 待接诊数量
        Long waitingCount = count(new LambdaQueryWrapper<Consultation>()
                .eq(Consultation::getDoctorId, doctorId)
                .eq(Consultation::getStatus, 0));
        stats.setWaitingCount(waitingCount);

        // 问诊中数量
        Long ongoingCount = count(new LambdaQueryWrapper<Consultation>()
                .eq(Consultation::getDoctorId, doctorId)
                .eq(Consultation::getStatus, 1));
        stats.setOngoingCount(ongoingCount);

        // 今日接诊数量（进行中和已完成的）
        LocalDateTime todayStart = LocalDate.now().atStartOfDay();
        Long todayCount = count(new LambdaQueryWrapper<Consultation>()
                .eq(Consultation::getDoctorId, doctorId)
                .ge(Consultation::getCreateTime, todayStart)
                .in(Consultation::getStatus, 1, 2));
        stats.setTodayCount(todayCount);

        // 总接诊数量（进行中和已完成的）
        Long totalCount = count(new LambdaQueryWrapper<Consultation>()
                .eq(Consultation::getDoctorId, doctorId)
                .in(Consultation::getStatus, 1, 2));
        stats.setTotalCount(totalCount);

        return stats;
    }

    @Override
    public Page<Consultation> getDoctorConsultations(Long doctorId, Integer status, Integer current, Integer size) {
        // 创建分页对象
        Page<Consultation> page = new Page<>(current, size);

        // 构建查询条件
        LambdaQueryWrapper<Consultation> wrapper = new LambdaQueryWrapper<Consultation>()
                .eq(Consultation::getDoctorId, doctorId)
                .orderByDesc(Consultation::getCreateTime);

        // 如果指定了状态，添加状态条件
        if (status != null) {
            wrapper.eq(Consultation::getStatus, status);
        }

        // 执行分页查询
        Page<Consultation> resultPage = page(page, wrapper);

        // 填充患者信息
        resultPage.getRecords().forEach(this::fillPatientInfo);

        return resultPage;
    }

    @Override
    public void updateDoctorOnlineStatus(Long doctorId, Boolean online) {
        // 查询医生是否存在
        SysUser doctor = sysUserMapper.selectById(doctorId);
        if (doctor == null) {
            throw new BusinessException("医生不存在");
        }

        // 更新在线状态
        SysUser updateDoctor = new SysUser();
        updateDoctor.setId(doctorId);
        updateDoctor.setOnline(online);

        int rows = sysUserMapper.updateById(updateDoctor);
        if (rows != 1) {
            throw new BusinessException("更新在线状态失败");
        }
    }

    // 填充患者信息的辅助方法
    private void fillPatientInfo(Consultation consultation) {
        if (consultation.getUserId() != null) {
            SysUser patient = sysUserMapper.selectById(consultation.getUserId());
            if (patient != null) {
                consultation.setPatientName(patient.getRealName());
                consultation.setPatientAvatar(patient.getAvatar());
            }
        }
    }

    @Override
    public Page<ConsultationVO> getUserConsultations(Long userId, Integer status, Integer current, Integer size) {
        // 创建分页对象
        Page<Consultation> page = new Page<>(current, size);

        // 构建查询条件
        LambdaQueryWrapper<Consultation> wrapper = new LambdaQueryWrapper<Consultation>()
                .eq(Consultation::getUserId, userId)
                .eq(status != null, Consultation::getStatus, status)
                .orderByDesc(Consultation::getCreateTime);

        // 执行分页查询
        Page<Consultation> consultationPage = page(page, wrapper);

        // 转换为VO对象
        Page<ConsultationVO> voPage = new Page<>(current, size, consultationPage.getTotal());
        List<ConsultationVO> voList = consultationPage.getRecords().stream()
                .map(consultation -> {
                    ConsultationVO vo = new ConsultationVO();
                    BeanUtils.copyProperties(consultation, vo);

                    // 获取医生信息
                    SysUser doctor = sysUserMapper.selectById(consultation.getDoctorId());
                    if (doctor != null) {
                        vo.setDoctorName(doctor.getRealName());
                        vo.setDoctorAvatar(doctor.getAvatar());
                    }

                    return vo;
                })
                .collect(Collectors.toList());

        voPage.setRecords(voList);
        return voPage;
    }
}
